package com.atung.parking.service.impl;

import com.atung.parking.config.auth.AuthUserMangerContext;
import com.atung.parking.config.result.ApiResult;
import com.atung.parking.config.result.PageInfoResponse;
import com.atung.parking.config.utils.DistanceUtil;
import com.atung.parking.config.utils.ParkingPointOperations;
import com.atung.parking.config.utils.QueryDataUtil;
import com.atung.parking.controller.DateConvertUtil;
import com.atung.parking.dto.LocationEntity;
import com.atung.parking.dto.ParkingPackageEntity;
import com.atung.parking.entity.BusApprovalRecord;
import com.atung.parking.entity.BusParkingIot;
import com.atung.parking.entity.BusParkingIotPackage;
import com.atung.parking.enums.*;
import com.atung.parking.export.ParkingIotPackageExportVO;
import com.atung.parking.export.PublicExportUtil;
import com.atung.parking.mapper.BusApprovalRecordMapper;
import com.atung.parking.mapper.BusParkingIotMapper;
import com.atung.parking.mapper.BusParkingIotPackageMapper;
import com.atung.parking.mapstruct.ParkingIotPackageConverter;
import com.atung.parking.request.query.AppQueryParkingIotRequest;
import com.atung.parking.request.query.QueryParkingPackageRequest;
import com.atung.parking.request.save.SaveOrUpdateParkingPackageRequest;
import com.atung.parking.request.save.UpdatePackageStateRequest;
import com.atung.parking.response.page.AppParkingIotPackageConfirmationResponse;
import com.atung.parking.response.page.AppParkingIotPackageResponse;
import com.atung.parking.response.page.ApprovalRecordResponse;
import com.atung.parking.service.ParkingPackageService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.val;
import org.apache.commons.lang3.time.FastDateFormat;
import org.springframework.beans.BeanUtils;
import org.springframework.data.geo.Point;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author Administrator
 */
@Service
public class ParkingPackageServiceImpl implements ParkingPackageService {

    @Resource
    private BusParkingIotPackageMapper busParkingIotPackageMapper;
    @Resource
    private BusParkingIotMapper busParkingIotMapper;
    @Resource
    private BusApprovalRecordMapper busApprovalRecordMapper;
    @Resource
    private ParkingIotPackageConverter parkingIotPackageConverter;
    @Resource
    private ParkingPointOperations parkingPointOperations;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private PublicExportUtil publicExportUtil;
    @Resource
    private QueryDataUtil queryDataUtil;

    @Override
    @Transactional
    public ApiResult saveParkingPackageService(SaveOrUpdateParkingPackageRequest request) {

        BusParkingIotPackage busParkingIotPackage = new BusParkingIotPackage();
        BeanUtils.copyProperties(request, busParkingIotPackage);
        busParkingIotPackage.setPackageType(request.getPackageType().name());
        busParkingIotPackage.setApplicableScope(request.getApplicableScope().name());
        AdminType roleType = AuthUserMangerContext.getAuthUserEntity().getRoleType();
        busParkingIotPackage.setState(ParkingPackageState.OFF_SHELF.getCode());
        BusParkingIot busParkingIot = this.validParkingIotId(request.getParkingIotId());
        if (Objects.isNull(busParkingIot)) {
            return ApiResult.fail("车场数据不存在");
        }
        if (roleType.equals(AdminType.ADMIN)) {
            //管理员需要判断是否为自己车场
            busParkingIotPackage.setDataSource(PackageSourceType.CUSTOMER_ADD.name());
        } else {
            busParkingIotPackage.setDataSource(PackageSourceType.PLATFORM_ADD.name());
            //设置用户
        }
        busParkingIotPackage.setSuperUserId(busParkingIot.getSuperUserId());
        if (Objects.nonNull(request.getId())) {
            //修改
            return null;
        }
        busParkingIotPackage.setRemainingStock(request.getStock());
        busParkingIotPackageMapper.insert(busParkingIotPackage);
        BusApprovalRecord busApprovalRecord = new BusApprovalRecord();
        busApprovalRecord.setApprovalType("创建");
        busApprovalRecord.setModelType(ApprovalModelType.PARKING_IOT_PACKAGE.name());
        busApprovalRecord.setModelId(busParkingIotPackage.getId());
        this.saveApprovalRecord(busApprovalRecord);
        return ApiResult.ok();
    }

    @Override
    public PageInfoResponse<BusParkingIotPackage> queryPackageListService(QueryParkingPackageRequest request) {
        QueryWrapper<BusParkingIotPackage> queryWrapper = createQueryWrapper(request);
        Page<BusParkingIotPackage> page = new Page<>(request.getPageNum(), request.getPageSize());
        Page<BusParkingIotPackage> busParkingIotPage = busParkingIotPackageMapper.selectPage(page, queryWrapper);
        PageInfoResponse<BusParkingIotPackage> pageResponse = new PageInfoResponse<>();
        pageResponse.setData(busParkingIotPage.getRecords());
        pageResponse.setTotal(busParkingIotPage.getTotal());
        return pageResponse;
    }

    @Override
    public ApiResult updatePackageStateService(UpdatePackageStateRequest request) {
        if (request.getState().equals(ParkingPackageState.SOLD_OUT)) {
            return ApiResult.fail("不可修改已售罄");
        }
        QueryWrapper<BusParkingIotPackage> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id", request.getId());
        AdminType roleType = AuthUserMangerContext.getAuthUserEntity().getRoleType();
        if (roleType.equals(AdminType.ADMIN)) {
            //管理员需要判断是否为自己车场
            queryWrapper.eq("super_user_id", AuthUserMangerContext.getUserId());
        }
        BusParkingIotPackage busParkingIotPackage = busParkingIotPackageMapper.selectOne(queryWrapper);
        if (ParkingPackageState.SOLD_OUT.getCode().equals(busParkingIotPackage.getState().intValue())) {
            return ApiResult.fail("当前套餐已售罄");
        }
        busParkingIotPackage.setState(request.getState().getCode());
        busParkingIotPackageMapper.updateById(busParkingIotPackage);
        BusApprovalRecord busApprovalRecord = new BusApprovalRecord();
        if (roleType.equals(AdminType.SUPERADMIN) &&
                request.getState().equals(ParkingPackageState.OFF_SHELF)) {
            //管理员需要判断是否为自己车场
            busApprovalRecord.setApprovalType("强制下架");
        } else {
            busApprovalRecord.setApprovalType(request.getState().getDescription());
        }
        busApprovalRecord.setModelType(ApprovalModelType.PARKING_IOT_PACKAGE.name());
        busApprovalRecord.setModelId(busParkingIotPackage.getId());
        this.saveApprovalRecord(busApprovalRecord);
        return ApiResult.ok();
    }

    @Override
    public List<ApprovalRecordResponse> queryApprovalParkingIotPackageListService(Long id) {
        QueryWrapper<BusApprovalRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("model_id", id);
        queryWrapper.eq("model_type", ApprovalModelType.PARKING_IOT_PACKAGE.name());
        List<BusApprovalRecord> approvalRecords = busApprovalRecordMapper.selectList(queryWrapper);
        return approvalRecords.stream().map(parkingIotPackageConverter::toApprovalResponse).collect(Collectors.toList());
    }

    @Override
    public ApiResult appParkingPackageDetailsService(Long id) {

        AppParkingIotPackageResponse appParkingIotPackageResponse = converterAppParkingIotPackageResponse(id);
        if(Objects.isNull(appParkingIotPackageResponse)){
            return ApiResult.fail("数据不存在");
        }
        if (StringUtils.hasText(appParkingIotPackageResponse.getLatitude())
                && StringUtils.hasText(appParkingIotPackageResponse.getLongitude())) {
            Point member1 = new Point(
                    Double.parseDouble(appParkingIotPackageResponse.getLongitude()),
                    Double.parseDouble(appParkingIotPackageResponse.getLatitude()));
            Point member = new Point(
                    36.674407,
                    117.132257);
            double distance = DistanceUtil.haversineDistance(member1, member);
            appParkingIotPackageResponse.setDistance(distance);
        } else {
            appParkingIotPackageResponse.setDistance(null);
        }
        return ApiResult.ok(appParkingIotPackageResponse);
    }

    @Override
    public ApiResult appParkingPackageConfirmationDetailsService(Long id) {

        BusParkingIotPackage busParkingIotPackage = busParkingIotPackageMapper.selectById(id);
        if(Objects.isNull(busParkingIotPackage)){
            return ApiResult.fail("套餐数据不存在");
        }
        BusParkingIot busParkingIot = busParkingIotMapper.selectById(busParkingIotPackage.getParkingIotId());
        AppParkingIotPackageConfirmationResponse appParkingIotPackageConfirmationResponse
                = new AppParkingIotPackageConfirmationResponse();
        BeanUtils.copyProperties(busParkingIotPackage, appParkingIotPackageConfirmationResponse);
        appParkingIotPackageConfirmationResponse.setApplicableScope(ApplicableScopeType.getDescriptionByName(busParkingIotPackage.getApplicableScope()));
        appParkingIotPackageConfirmationResponse.setRatePerHour(busParkingIot.getRatePerHour());
        appParkingIotPackageConfirmationResponse.setName(busParkingIot.getName());
        appParkingIotPackageConfirmationResponse.setDetailedAddress(busParkingIot.getDetailedAddress());
        appParkingIotPackageConfirmationResponse.setImagePath(busParkingIot.getImagePath());
        //
        return ApiResult.ok(appParkingIotPackageConfirmationResponse);
    }

    @Override
    public void exportParkingIotPackageService(QueryParkingPackageRequest request, HttpServletResponse httpServletResponse) {
        QueryWrapper<BusParkingIotPackage> queryWrapper = createQueryWrapper(request);
        List<BusParkingIotPackage> busParkingIotPackages = busParkingIotPackageMapper.selectList(queryWrapper);
        List<ParkingIotPackageExportVO> collect = busParkingIotPackages.stream().map(item -> {
            ParkingIotPackageExportVO parkingIotPackageExportVO = parkingIotPackageConverter.toExportVo(item);
            FastDateFormat formatter = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss");
            // 格式化日期时间
            try {
                String formattedDate = formatter.format(Long.valueOf(item.getCreatorTime()));
                parkingIotPackageExportVO.setCreatorTime(formattedDate);
            } catch (Exception e) {
                parkingIotPackageExportVO.setCreatorTime("时间格式化出现问题");
            }
            return parkingIotPackageExportVO;

        }).collect(Collectors.toList());
        try {
            publicExportUtil.exportReport(ExportType.PARKING_PACKAGE_EXPORT, collect, httpServletResponse);
        } catch (Exception e) {

        }
    }

    @Override
    public ApiResult queryAvailableTimeService(Long id) {

        BusParkingIotPackage busParkingIotPackage = busParkingIotPackageMapper.selectById(id);
        if (Objects.isNull(busParkingIotPackage)) {
            return ApiResult.fail("套餐数据不存在");
        }
        //判断套餐类型
        if (ApplicableScopeType.WORKDAY.name().equals(busParkingIotPackage.getApplicableScope())) {
            List<String> workday = queryDataUtil.createWeekday();
            return ApiResult.ok(workday);
            //工作日可以时间
        } else if (ApplicableScopeType.WEEKEND_OR_HOLIDAY.name().equals(busParkingIotPackage.getApplicableScope())) {
            List<String> holiday = queryDataUtil.createHoliday();
            return ApiResult.ok(holiday);
        }

        return ApiResult.ok();
    }

    public QueryWrapper<BusParkingIotPackage> createQueryWrapper(QueryParkingPackageRequest request) {
        QueryWrapper<BusParkingIotPackage> queryWrapper = new QueryWrapper<>();
        //联系电话
        if (StringUtils.hasText(request.getApplicableScope())) {
            queryWrapper.eq("applicable_scope", request.getApplicableScope());
        }
        //厂商
        if (Objects.nonNull(request.getPackageType())) {
            queryWrapper.eq("package_type", request.getPackageType().name());
        }
        //时间查询
        if (StringUtils.hasText(request.getStartData()) && StringUtils.hasText(request.getEndData())) {
            Long start = DateConvertUtil.convertQueryStartToMillis(request.getStartData());
            Long end = DateConvertUtil.convertQueryEndToMillis(request.getEndData());
            if (Objects.nonNull(request.getStartData()) && Objects.nonNull(request.getEndData())) {
                queryWrapper.between("creator_time", start, end);
            }

        }
        if (Objects.nonNull(request.getParkingIotId())) {
            queryWrapper.eq("parking_iot_id", request.getParkingIotId());
        }
        AdminType roleType = AuthUserMangerContext.getAuthUserEntity().getRoleType();
        if (roleType.equals(AdminType.ADMIN)) {
            //管理员需要判断是否为自己车场
            queryWrapper.eq("super_user_id", AuthUserMangerContext.getUserId());
        }
        queryWrapper.orderByDesc("creator_time");
        return queryWrapper;

    }

    public void saveApprovalRecord(BusApprovalRecord busApprovalRecord) {
        busApprovalRecordMapper.insert(busApprovalRecord);
    }

    public BusParkingIot validParkingIotId(Long parkingIotId) {
        QueryWrapper<BusParkingIot> queryWrapper = new QueryWrapper<BusParkingIot>();

        queryWrapper.eq("id", parkingIotId);
        //审核通过
        queryWrapper.eq("approval_status", ParkingIotApprovalState.APPROVED.getCode());
        AdminType roleType = AuthUserMangerContext.getAuthUserEntity().getRoleType();
        if (roleType.equals(AdminType.ADMIN)) {
            //管理员需要判断是否为自己车场
            queryWrapper.eq("super_user_id", AuthUserMangerContext.getAuthUserEntity().getUserId());
        }
        return busParkingIotMapper.selectOne(queryWrapper);

    }

    @Override
    public ApiResult<List<AppParkingIotPackageResponse>> appRecommendParkingPackage
            (AppQueryParkingIotRequest appQueryParkingIotRequest) {
        //获取推荐
        List<LocationEntity> locationEntities = parkingPointOperations.queryAllParkingIds(appQueryParkingIotRequest.getLat(), appQueryParkingIotRequest.getLon());
        return ApiResult.ok(locationEntities.stream().map(item -> {
                            AppParkingIotPackageResponse appParkingIotPackageResponse = converterAppParkingIotPackageResponse(item.getId());
                            if (Objects.isNull(appParkingIotPackageResponse)) {
                                return null;
                            }
                            appParkingIotPackageResponse.setDistance(item.getDistance());
                            return appParkingIotPackageResponse;
                        }).filter(Objects::nonNull)
                        .collect(Collectors.toList())
                        .stream()
                        .filter(item -> !item.getPackageNumber().equals(0))
                        .collect(Collectors.toList())
        );
    }

    @Override
    public ApiResult<List<AppParkingIotPackageResponse>> appQueryParkingPackageService(AppQueryParkingIotRequest appQueryParkingIotRequest) {

        QueryWrapper<BusParkingIot> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("approval_status", ParkingIotApprovalState.APPROVED.getCode());
        if (StringUtils.hasText(appQueryParkingIotRequest.getName())) {
            queryWrapper.like("name", appQueryParkingIotRequest.getName());
        }
        List<BusParkingIot> busParkingIots = busParkingIotMapper.selectList(queryWrapper);
        List<AppParkingIotPackageResponse> collect = busParkingIots.stream().map(item -> {
                    AppParkingIotPackageResponse appParkingIotPackageResponse = converterAppParkingIotPackageResponse(item.getId());
                    if (Objects.isNull(appParkingIotPackageResponse)) {
                        return null;
                    }
                    Point member1 = new Point(
                            Double.parseDouble(item.getLongitude()),
                            Double.parseDouble(item.getLatitude()));
                    Point member = new Point(
                            36.674407,
                            117.132257);
                    double distance = DistanceUtil.haversineDistance(member1, member);
                    appParkingIotPackageResponse.setDistance(distance);
                    return appParkingIotPackageResponse;
                }).filter(Objects::nonNull)
                .filter(item->!Objects.isNull(item.getPackageList()))
                .sorted(Comparator.comparingDouble(AppParkingIotPackageResponse::getDistance))
                .collect(Collectors.toList());
        if(Objects.nonNull(appQueryParkingIotRequest.getPackageType())){
            collect=collect.stream()
                    .filter(response -> response.getPackageList() != null)
                    .peek(response -> {
                        // 过滤每个 response 中的 packageList
                        List<ParkingPackageEntity> filteredPackages = response.getPackageList().stream()
                                .filter(packageEntity -> appQueryParkingIotRequest.getPackageType().name().equals(packageEntity.getPackageType()))
                                .collect(Collectors.toList());
                        response.setPackageList(filteredPackages); // 更新 packageList
                    })
                    .filter(response -> !CollectionUtils.isEmpty(response.getPackageList()))
                    .collect(Collectors.toList());
        }
        return ApiResult.ok(collect);
    }

    public AppParkingIotPackageResponse converterAppParkingIotPackageResponse(Long id) {

        AppParkingIotPackageResponse appParkingIotPackageResponse = new AppParkingIotPackageResponse();
        BusParkingIot busParkingIot = busParkingIotMapper.selectById(id);
        if (Objects.isNull(busParkingIot) ||
                !ParkingIotApprovalState.APPROVED.getCode().equals(busParkingIot.getApprovalStatus())
        ) {
            return null;
        }
        BeanUtils.copyProperties(busParkingIot, appParkingIotPackageResponse);

        //获取停车场套餐
        QueryWrapper<BusParkingIotPackage> queryWrapper = new QueryWrapper<BusParkingIotPackage>();
        queryWrapper.eq("parking_iot_id", id);
        queryWrapper.orderByDesc("creator_time");
        List<BusParkingIotPackage> busParkingIotPackages = busParkingIotPackageMapper.selectList(queryWrapper);
        if (CollectionUtils.isEmpty(busParkingIotPackages)) {
            appParkingIotPackageResponse.setPackageNumber(0);
            return appParkingIotPackageResponse;

        }
        appParkingIotPackageResponse.setPackageNumber(busParkingIotPackages.size());

        appParkingIotPackageResponse.setPackageList(
                busParkingIotPackages.stream().map(item -> {
                    ParkingPackageEntity parkingPackageEntity = new ParkingPackageEntity();
                    BeanUtils.copyProperties(item, parkingPackageEntity);
                    parkingPackageEntity.setApplicableScope(ApplicableScopeType.getDescriptionByName(item.getApplicableScope()));
                    return parkingPackageEntity;
                }).collect(Collectors.toList()));
        ;
        return appParkingIotPackageResponse;
    }


}
